﻿using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace SQLFileComparer
{
    class BackProcessor : MainAction
    {
        public BackProcessor(ActionParams actionParams)
            : base(actionParams)
        {
        }

        private void Decode()
        {
            using (var outStream = new MemoryStream())
            {
                using (var tmpStream = new MemoryStream(DataHolder.ToArray()))
                using (var decompress = new DeflateStream(tmpStream, CompressionMode.Decompress))
                    decompress.CopyTo(outStream);

                var bytes = outStream.ToArray();
                WriteBytes(bytes);
            }
        }

        private void DeCript()
        {
            var bytes = Convert.FromBase64String(Encoding.Default.GetString(DataHolder.ToArray()));

            var key = Convert.FromBase64String(Params.Key);
            for (var i = 0; i < bytes.Length; i++)
                bytes[i] ^= key[i % 1024];

            WriteBytes(bytes);
        }

        public int Process(string file, string dirName)
        {
            Debug.Assert(Directory.Exists(dirName));
            LoadFromFile(file);

            // dechipr
            DeCript();

            Decode();

            // extract files
            if (dirName[dirName.Length - 1] != '\\')
                dirName = dirName + '\\';

            DataHolder.Seek(0, SeekOrigin.Begin);
            while (true)
            {
                // read name lenth
                var lenth = DataHolder.ReadByte();
                if (lenth < 0) break;

                // read name
                var bytes = new byte[lenth];
                var readCount = DataHolder.Read(bytes, 0, lenth);
                if (readCount != lenth) return CUnexpectdEnd;
                var fileName = Encoding.Default.GetString(bytes);

                // read body lenth
                bytes = new byte[sizeof(int)];
                readCount = DataHolder.Read(bytes, 0, bytes.Length);
                if (readCount != sizeof(int)) return CUnexpectdEnd;
                lenth = BitConverter.ToInt32(bytes, 0);
                if (lenth <= 0) return CBadData;

                // read body
                bytes = new byte[lenth];
                readCount = DataHolder.Read(bytes, 0, bytes.Length);
                if (readCount != lenth) return CUnexpectdEnd;

                // save file
                fileName = dirName + fileName;
                Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                using (var fileStream = new FileStream(fileName, FileMode.Create))
                    fileStream.Write(bytes, 0, bytes.Length);
            }

            return COk;
        }
    }
}
